package com.baijia.services.impl;

import com.baijia.dao.IInternalServiceTokenDao;
import com.baijia.services.ISignValidationService;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class SignValidationServiceImpl implements ISignValidationService {

    @Resource
    private IInternalServiceTokenDao internalServiceTokenDao;

    private LoadingCache<Integer, String> tokenCache = CacheBuilder.newBuilder().maximumSize(100)
        .expireAfterWrite(4, TimeUnit.HOURS).build(new CacheLoader<Integer, String>() {
            @Override
            public String load(Integer sid) throws Exception {
                return internalServiceTokenDao.getToeknBySid(sid);
            }
        });

    public static void main(String[] args) {
        String smsCode = "353592";
        String mobile = "你好";
        String newPassword = "lmy111111";
        String retypePassword = "lmy111111";

        Long time = System.currentTimeMillis();
        String token = "2ZdJIR6emDmI59a";

        TreeMap<String, Object> params = new TreeMap<String, Object>();
        params.put("smsCode", smsCode);
        params.put("mobile", mobile);
        params.put("newPassword", newPassword);
        params.put("retypePassword", retypePassword);

        StringBuffer sb = new StringBuffer();
        for (Entry<String, Object> param : params.entrySet()) {
            if (param.getValue() != null) {
                sb.append(param.getKey()).append("=").append(param.getValue().toString()).append("&");
            }
        }
        sb.deleteCharAt(sb.length() - 1);

        sb.append(time).append(DigestUtils.md5Hex(token));

        System.out.println("Time : " + time);
        System.out.println("Before sign : " + sb.toString());
        System.out.println("After sign : " + DigestUtils.md5Hex(sb.toString()));
    }

    @Override
    public boolean validate(Map<String, Object> params, Integer sid, Long time, String signToVerify) {
        // 调试用 | 不要打到后台日志中
        // log.info("params : {}, sid : {}, time : {}, signToVerify : {}", params, sid, time, signToVerify);

        StringBuffer sb = new StringBuffer();
        for (Entry<String, Object> param : params.entrySet()) {
            if (param.getValue() != null) {
                sb.append(param.getKey()).append("=").append(param.getValue().toString()).append("&");
            }
        }
        sb.deleteCharAt(sb.length() - 1);

        String token = StringUtils.EMPTY;
        try {
            token = tokenCache.get(sid);
        } catch (ExecutionException e) {
            log.error("Failed to get token", e);
            return false;
        }

        log.info("token : {}", token);
        if (StringUtils.isEmpty(token)) {
            log.error("token is empty");
            return false;
        }

        sb.append(time).append(DigestUtils.md5Hex(token));
        // 调试用 | 不要打到后台日志中
        // log.info("Before sign : {}", sb.toString());

        boolean result = signToVerify.equals(DigestUtils.md5Hex(sb.toString()));
        if (!result) {
            log.error("Sign validation failed");
        }

        return result;
    }
}
